package main

import (
	"database/sql"
	"fmt"
	"net/http"
	"os"
	"runtime"

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mssql"
	_ "github.com/jinzhu/gorm/dialects/postgres"
	_ "github.com/jinzhu/gorm/dialects/sqlite"
	"github.com/op/go-logging"
	"github.com/skratchdot/open-golang/open"
)

var logger = logging.MustGetLogger("nbgw")

//`%{color}%{time:15:04:05.000} %{shortfunc} %{level:.4s} %{id:03x}%{color:reset} %{message}`,
var format = logging.MustStringFormatter(
	`%{color}%{time:15:04:05.000} %{message}`,
)

var dbConn *sql.DB
var gldb *gorm.DB
var server *Server

const TOKEN_LENGTH int = 7
const protocol string = "udp4"
const devRegPrefix string = "ep="
const readBufferSize int = 1024

func dbInitialize() {
	var err error
	gldb, err = gorm.Open(GlobalConfig().Dbtype, GlobalConfig().Dburl)
	if err != nil {
		logger.Warning("open database failed. ", err)
		return
	}
	logger.Infof("connect to %s:%s succ.", GlobalConfig().Dbtype, GlobalConfig().Dburl)
	gldb.AutoMigrate(
		&Device{},
		&DeviceAttr{},
		&CoapSession{},
		&User{},
		&UserAuthToken{},
		&CoapMessage{},
		&App{},
	)
}

func loggingInit(level string) {
	logFile, err := os.OpenFile("nbgw.log", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("open log file failed.", err)
		return
	}
	//defer logFile.Close()

	backend1 := logging.NewLogBackend(logFile, "", 0)
	backend2 := logging.NewLogBackend(os.Stderr, "", 0)

	backend1Formatter := logging.NewBackendFormatter(backend1, format)
	backend2Formatter := logging.NewBackendFormatter(backend2, format)

	logging.SetBackend(backend1Formatter, backend2Formatter)
}

func WsApiServer() {
	gin.SetMode(gin.ReleaseMode)
	var router *gin.Engine
	if runtime.GOOS == "windows" {
		router = gin.New()
	} else {
		router = gin.Default()
	}
	router.GET("/", func(c *gin.Context) {
		c.Redirect(http.StatusFound, "/simple/portal/")
	})
	router.StaticFS("/simple/", FS(false))
	router.GET("/favicon.ico", func(c *gin.Context) {
		data, err := FSByte(false, "/portal/static/img/favicon.ico")
		if err != nil {
			c.AbortWithStatus(http.StatusNotFound)
			return
		}
		c.Data(200, "image/x-icon", data)
	})
	//portal_v1(router)
	portalapiInitialize(router)
	v3apiInitialize(router)
	logger.Infof("prepare listen http on %d", GlobalConfig().WebPort)

	if runtime.GOOS == "windows" {
		open.Run(fmt.Sprintf("http://localhost:%d/", GlobalConfig().WebPort))
	} else {
		logger.Infof("please open browser to http://localhost:%d/", GlobalConfig().WebPort)
	}
	router.Run(fmt.Sprintf(":%d", GlobalConfig().WebPort))
}

func main() {
	readConfig("nbgw.json")
	loggingInit(GlobalConfig().LoggingLevel)
	dbInitialize()

	//CoAP Server
	go CoAPServerInit()

	//Portal API Server
	go WsApiServer()

	//udp proxy server
	go UdpProxyServer()

	//sleep forever.
	make(chan bool) <- true
}

//go get github.com/mjibson/esc
//go:generate esc -o portal.go portal
